#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <sys/epoll.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <time.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <mosquitto.h>

#define HOST "broker-cn.emqx.io"
#define PORT  1883
#define KEEP_ALIVE 60
bool session = true;
char recv_buf[1024] = {0};
int len=0;   //接收rtcm数据长度
const char caster_agent[] = "NTRIP NTRIPCaster/20181206";
const char client_agent[] = "NTRIP NTRIPClient/20181206";
const char server_agent[] = "NTRIP NTRIPServer/20181206";
const char base64_code_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


void print_char(char *src, int len)
{
	for(int i = 0; i < len; ++i){
		printf("%c", (unsigned char)src[i]);
	}
	printf("\n");
}

void print_char_hex(char *src, int len)
{
	for(int i = 0; i < len; ++i){
		printf("%02x ", (unsigned char)src[i]);
	}
	printf("\n");
}

int check_sum(char *src)
{
	int sum = 0, num = 0;

	sscanf(src, "%*[^*]*%x", &num);
	for(int i = 1; src[i] != '*'; ++i){
		sum ^= src[i];
	}
	return sum - num;
}

int ch2index(char ch)
{
	int i;
	for(i=0; i < (int)strlen(base64_code_table); ++i){
		if(ch == base64_code_table[i])
			return i;
	}
	return -1;
}

char index2chr(int index)
{
	return base64_code_table[index];
}


int base64_encode(char *src, char *result)
{
	char temp[3] = {0};
	int i = 0, j = 0, count = 0;
	int len = strlen(src);
	if(len==0)
		return -1;

	if(len%3 != 0){
		count = 3 - len%3;
	}

	while(i < len){
		strncpy(temp, src+i, 3);
		result[j+0] = index2chr((temp[0]&0xFC)>>2);
		result[j+1] = index2chr(((temp[0]&0x3)<<4) | ((temp[1]&0xF0)>>4));
		if(temp[1] == 0)
			break;
		result[j+2] = index2chr(((temp[1]&0xF)<<2) | ((temp[2]&0xC0)>>6));
		if(temp[2] == 0)
			break;
		result[j+3] = index2chr(temp[2]&0x3F);
		i+=3;
		j+=4;
		memset(temp, 0x0, 3);
	}

	while(count){
		result[j+4-count] = '=';
		--count;
	}

	return 0;
}


int base64_decode(char *src, char *usr, char *pwd)
{
	char result[64] = {0};
	char temp[4] = {0};
	int i = 0;
	int j = 0;
	int len = strlen(src);
	if(len==0 || len%4!=0)
		return -1;

	while(i < len){
		strncpy(temp, src+i, 4);
		result[j+0] = ((ch2index(temp[0])&0x3F) << 2) | ((ch2index(temp[1])&0x3F) >> 4);
		if(temp[2] == '=')
			break;
		result[j+1] = ((ch2index(temp[1])&0xF) << 4) | ((ch2index(temp[2])&0x3F) >> 2);
		if(temp[3] == '=')
			break;
		result[j+2] = ((ch2index(temp[2])&0x3) << 6) | ((ch2index(temp[3])&0x3F));
		i+=4;
		j+=3;
		memset(temp, 0x0, 4);
	}
	sscanf(result, "%[^:]%*c%[^\n]", usr, pwd);

	return 0;
}


int get_sourcetable(char *data, int data_len)
{
	int fsize = 0;

	FILE *fp = fopen("./config/sourcetable.dat", "r");
	if (fp != NULL) {
		fseek(fp, 0, SEEK_END);
		fsize = (int)ftell(fp);
		rewind(fp);
	}

	char *source = (char *)malloc(fsize);
	fread(source, sizeof(char), fsize, fp);

	snprintf(data, data_len, "SOURCETABLE 200 OK\r\n"
		"Server: %s\r\n"
		"Content-Type: text/plain\r\n"
		"Content-Length: %d\r\n"
		"%s"
		"ENDSOURCETABLE\r\n",
		caster_agent, fsize , source);

	fclose(fp);
	free(source);
	source = NULL;

	return 0;
}

int main(int argc, char *argv[])
{
	int m_sock,n;
	time_t start, stop;
	char recv_buf[1024] = {0};
	char request_data[1024] = {0};
	char userinfo_raw[48] = {0};
  	char userinfo[64] = {0};
	char buff[256];
	int rtcm_de[1024] = {0};
	char CRC[10]={0};
 
	char server_ip[] = "117.135.142.201";
	int server_port = 8001;
   	
	char mountpoint[] = "RTCM33_GRCE";
	char user[] = "abcg2505";
	char passwd[] = "hj6odmdc";
	char gpgga[] = "$GPGGA,083552.00,3000.0000000,N,11900.0000000,E,1,08,1.0,0.000,M,100.000,M,,*57\r\n";
	struct mosquitto *mosq = NULL;
    
    mosquitto_lib_init();    //初始化
	mosq = mosquitto_new(NULL,session,NULL);    //创建爱你一个新的客户端
	if(!mosq){
        printf("create client failed..\n");
        mosquitto_lib_cleanup();
        return 1;
    }

	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(server_port);
	server_addr.sin_addr.s_addr = inet_addr(server_ip);
	
	/* 把用户名和密码base64编码 */
	snprintf(userinfo_raw, 63 , "%s:%s", user, passwd);
	base64_encode(userinfo_raw, userinfo);
 
 	/* ntrip协议连接命令 */
	snprintf(request_data, 1023,
		"GET /%s HTTP/1.1\r\n"
		"User-Agent: %s\r\n"
		"Accept: */*\r\n"
		"Connection: close\r\n"
		"Authorization: Basic %s\r\n"
		"\r\n"
		, mountpoint, client_agent, userinfo);

	m_sock = socket(AF_INET, SOCK_STREAM, 0);		//int socket(int domain, int type, int protocol)		AF_INET为IPv4协议  SOCK_STREAM为TCP连接
	if(m_sock == -1) {
		printf("create socket fail\n");
		exit(1);
	}

	/* TCP连接. */
	int ret = connect(m_sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));		//连接server
	if(ret < 0){
		printf("connect caster fail\n");
		exit(1);
	}

	/* 根据协议发送连接命令. */
	ret = send(m_sock, request_data, strlen(request_data), 0);		//发送数据
	if(ret < 0){
		printf("send request fail\n");
		exit(1);
	}

	/* Wait for request to connect caster success. */
	while(1){
		ret = recv(m_sock, (void *)recv_buf, sizeof(recv_buf), 0);
		if(ret > 0 && !strncmp(recv_buf, "ICY 200 OK\r\n", 12)){
			ret = send(m_sock, gpgga, strlen(gpgga), 0);    //发送gpgga信息
			if(ret < 0){
				printf("send gpgga data fail\n");
				exit(1);
			}
			printf("send gpgga data ok\n");
			break;
		}
	}

	/* 接收caster发送的信息. */
	while(1){
		start = time(NULL);
		len = recv(m_sock, (void *)recv_buf, sizeof(recv_buf), 0);
		stop = time(NULL);
		if(len > 0){    //如果收到数据
            printf("recv data:[%d] used time:[%d]\n", len, (int)(stop - start));  //ret-收到数据个数/长度；recv_buf-收到数据
			print_char(recv_buf, len);
			if(mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE)){
			   fprintf(stderr, "Unable to connect.\n");
			   return 1;
		    }
		   /* int loop = mosquitto_loop_start(mosq);
		    if(loop != MOSQ_ERR_SUCCESS)
			{
				printf("mosquitto loop error\n");
				return 1;
			}*/
			mosquitto_publish(mosq,NULL,"dwm/rtcm",len,recv_buf,0,0);
			
			//mosquitto_destroy(mosq);     //释放客户端
            mosquitto_lib_cleanup();   //使用完之后清除工作
			   
	
		}
		else{
			printf("remote socket close!!!\n");
			break;
		}
	}

	close(m_sock);

	return  0;
}
